package cn.core.tool.util;

import org.apache.commons.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.Security;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 工具类
 */
public final class CoreTool {

  /**
   * RSA 私钥
   */
  public static final String PRIVATE_KEY = "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";

  /**
   * RSA 公钥
   */
  public static final String PUBLIC_KEY = "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAmN3JifQM+oMe+PeXFD/WoZm046XfXt0aWg30NsOFVyasT8xzWLKrNn34wUPGU2sVujJJfjKY6VnmGqHIAH0pmi9WtgD7nZgbNIl85LkJTFgEXJm6JILe9jTBTMI1qodlwnbXWCUIibTwQE/YoljHceWCJP7MFJT6u/hbi1HJlGet9C4fzDZ6znNRY6eBbWNBDHHgbqmx9q3dKdAUCGpHDQ5eVhe6CeCwh6bAtfopV+v1XStwOC0J8Gxk5sxVYltEI6WdRdAv+RyZ2ueUPAqp78uTF5Uvtx6VRX5PTcPe/G1VPTndMjM657Gy88yZJ4KIG8Ta7hHJ8CTZ0Fri5U+OAua2/CKmsPbDezSlixQu7L49+7eU867Lc6ZxhcLDai4d4o8kUK2Yh9TIerpFzSHQG2MUVhKcm3h2Oze89sdiDbeTlPVb3z8KSG8h3t+bYIjqDU9by8/3GAk32HJVIug/9z631GLu1RS1m7Ih6gJe/5Zmj6y5E2iGyOT+37j54pOXwi+KA53JIzdMdbVNSO5H+qrJGVl68RqNYAcCjU7FZ70buEpS1C+dEiAMKxiAahtMClAjr5p0e+v6KB6ua/opUhojg6zPilJ390a+s6+A4XPzLaUwc5xlWYTzpHwJz9XA2ExTDHujJ/HkUAg3FAfh2i2ry37M+eK9qYhSgHaO63kCAwEAAQ==";

  /**
   * AES 密钥
   */
  public static final String AES_KEY = "Xy7qBgpcdXlL4j5hphpKwA==";

  /**
   * AES 密钥 >>> 密码
   */
  public static final String AES_KEY_PASSWORD = "BaJxHLDLszKJWspUOqx/YQ==";

  /**
   * mysql
   */
  public static final String mysql = "mysql";

  /**
   * oracle
   */
  public static final String oracle = "oracle";

  /**
   * oracle11
   */
  public static final String oracle11 = "oracle11";

  /**
   * 空字符串
   */
  public static final String nullStr = "";

  /**
   * 36位uuid
   */
  public static String getUUID36() {
    return UUID.randomUUID().toString();
  }

  /**
   * 32位uuid
   */
  public static String getUUID32() {
    return UUID.randomUUID().toString().replaceAll("-", "");
  }

  /**
   * 字符串是null或空字符串或全空格字符串<br>
   * 返回true
   */
  public static boolean isNullStr(String str) {
    return str == null ? true : (str.trim().length() == 0 ? true : false);
  }

  /**
   * 字符串非null或空字符串或全空格字符串<br>
   * 返回true
   */
  public static boolean isNotNullStr(String str) {
    return str != null && str.trim().length() != 0;
  }

  /**
   * 集合非null或空集合<br>
   * 返回true
   */
  public static boolean isNotEmpty(Collection<?> arg) {
    return arg != null && (!arg.isEmpty());
  }

  /**
   * 集合是null或空集合<br>
   * 返回true
   */
  public static boolean isEmpty(Collection<?> arg) {
    return arg == null ? true : arg.isEmpty();
  }

  /**
   * Map非null或空Map<br>
   * 返回true
   */
  public static boolean isNotEmpty(Map<?, ? extends Object> map) {
    return map != null && (!map.isEmpty());
  }

  /**
   * Map是null或空Map<br>
   * 返回true
   */
  public static boolean isEmpty(Map<?, ? extends Object> map) {
    return map == null ? true : map.isEmpty();
  }

  /**
   * 对象是null或对象的成员变量值都是null<br>
   * 返回true
   */
  public static boolean isNullEo(Object o) {
    try {
      if (o != null) {
        // 取得目标对象的字段集合
        LinkedHashSet<Field> fields = new LinkedHashSet<Field>();
        Class<?> c = o.getClass();
        while (c != null) {
          fields.addAll(Arrays.asList(c.getDeclaredFields()));
          c = c.getSuperclass();
        }
        if (CoreTool.isNotEmpty(fields)) {
          for (Field field : fields) {
            try {
              // 目标对象成员变量有get方法 就进行非空判断
              if (o.getClass().getMethod("get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1)).invoke(o) != null) {
                return false;
              }
            } catch (NoSuchMethodException e) {
            }
          }
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
    return true;
  }

  /**
   * 对象非null并且对象的任一成员变量值非null<br>
   * 返回true
   */
  public static boolean isNotNullEo(Object o) {
    return !CoreTool.isNullEo(o);
  }

  /**
   * 源对象属性拷贝到目标对象<br>
   * is参数为true时只拷贝非空属性
   */
  public static void copyProperties(Object source, Object target, Boolean is) {
    try {
      if (source != null && target != null && is != null) {
        // 取得目标对象的字段集合
        LinkedHashSet<Field> fields = new LinkedHashSet<Field>();
        Class<?> c = source.getClass();
        while (c != null) {
          fields.addAll(Arrays.asList(c.getDeclaredFields()));
          c = c.getSuperclass();
        }
        if (CoreTool.isNotEmpty(fields)) {
          for (Field field : fields) {
            if (field.getType().toString().indexOf("class") != -1) {
              try {
                Object o = source.getClass().getMethod("get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1)).invoke(source);
                if (is) {
                  if (o != null) {
                    target.getClass().getMethod("set" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1), Class.forName(field.getType().toString().replaceAll("class", "").trim())).invoke(target, o);
                  }
                } else {
                  target.getClass().getMethod("set" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1), Class.forName(field.getType().toString().replaceAll("class", "").trim())).invoke(target, o);
                }
              } catch (NoSuchMethodException e) {
              }
            }
          }
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  /**
   * 源对象属性拷贝到目标对象
   */
  public static void copyProperties(Object source, Object target) {
    CoreTool.copyProperties(source, target, false);
  }

  /**
   * 下划线 >>> 首字母大写驼峰
   */
  public static String getInitialCaseHumpByUnderline(String str) {
    StringBuilder rStr = new StringBuilder();
    if (CoreTool.isNotNullStr(str)) {
      char[] chars = str.toCharArray();
      boolean is = false;
      for (char c : chars) {
        if (c == 95) {
          is = true;
        } else {
          if (is) {
            rStr.append(Character.toUpperCase(c));
          } else {
            rStr.append(Character.toLowerCase(c));
          }
          is = false;
        }
      }
      rStr.setCharAt(0, Character.toUpperCase(rStr.substring(0, 1).charAt(0)));
    }
    return rStr.toString();
  }

  /**
   * 下划线 >>> 首字母小写驼峰
   */
  public static String getInitialLowercaseHumpByUnderline(String str) {
    StringBuilder rStr = new StringBuilder();
    if (CoreTool.isNotNullStr(str)) {
      char[] chars = str.toCharArray();
      boolean is = false;
      for (char c : chars) {
        if (c == 95) {
          is = true;
        } else {
          if (is) {
            rStr.append(Character.toUpperCase(c));
          } else {
            rStr.append(Character.toLowerCase(c));
          }
          is = false;
        }
      }
      rStr.setCharAt(0, Character.toLowerCase(rStr.substring(0, 1).charAt(0)));
    }
    return rStr.toString();
  }

  /**
   * 驼峰 >>> 大写下划线
   */
  public static String getCaseUnderlineByHump(String str) {
    StringBuilder rStr = new StringBuilder();
    if (CoreTool.isNotNullStr(str)) {
      char[] chars = str.toCharArray();
      for (char c : chars) {
        if (Character.isUpperCase(c)) {
          if (rStr.length() != 0) {
            rStr.append("_");
          }
          rStr.append(c);
        } else {
          rStr.append(c);
        }
      }
    }
    return rStr.toString().toUpperCase();
  }

  /**
   * 驼峰 >>> 小写下划线
   */
  public static String getLowercaseUnderlineByHump(String str) {
    StringBuilder rStr = new StringBuilder();
    if (CoreTool.isNotNullStr(str)) {
      char[] chars = str.toCharArray();
      for (char c : chars) {
        if (Character.isUpperCase(c)) {
          if (rStr.length() != 0) {
            rStr.append("_");
          }
          rStr.append(c);
        } else {
          rStr.append(c);
        }
      }
    }
    return rStr.toString().toLowerCase();
  }

  /**
   * 模板字符串替换
   */
  public static String renderString(String content, Map<String, String> map) {
    Set<Map.Entry<String, String>> sets = map.entrySet();
    for (Map.Entry<String, String> entry : sets) {
      String regex = "\\$\\{" + entry.getKey() + "\\}";
      Pattern pattern = Pattern.compile(regex);
      Matcher matcher = pattern.matcher(content);
      content = matcher.replaceAll(entry.getValue() != null ? entry.getValue() : "");
    }
    return content;
  }

  /**
   * 资源文件路径 >>> 文件内容字符串
   */
  public static String getStrByFileResourcesPath(String str) {
    StringBuilder str1 = new StringBuilder();
    String str2 = null;
    BufferedReader reader = null;
    try {
      reader = new BufferedReader(new InputStreamReader(CoreTool.class.getResourceAsStream(str)));
      while ((str2 = reader.readLine()) != null) {
        str1.append(str2).append("\n");
      }
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      if (reader != null) {
        try {
          reader.close();
        } catch (IOException e1) {
        }
      }
    }
    return str1.toString();
  }

  /**
   * 文件路径 >>> 文件内容字符串
   */
  public static String getContentStrByFilePath(String str) {
    StringBuilder str1 = new StringBuilder();
    String str2 = null;
    File file = new File(str);
    BufferedReader reader = null;
    try {
      reader = new BufferedReader(new FileReader(file));
      while ((str2 = reader.readLine()) != null) {
        str1.append(str2).append("\n");
      }
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      if (reader != null) {
        try {
          reader.close();
        } catch (IOException e1) {
        }
      }
    }
    return str1.toString();
  }

  /**
   * 文件内容字符串和文件绝对路径 >>> 生成文件
   */
  public static void getFileByContentStrAndPath(String content, String path) {
    try {
      File f = new File(path);
      if (!f.exists()) {
        new File(path.substring(0, path.lastIndexOf(File.separator))).mkdirs();
      }
      FileOutputStream fop = new FileOutputStream(f);
      OutputStreamWriter writer = new OutputStreamWriter(fop, "UTF-8");
      writer.append(content);
      writer.close();
      fop.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  /**
   * 字节输入流 >>> 字符串
   */
  public static String getStrByInputStream(InputStream inputStream) {
    StringBuilder str1 = new StringBuilder();
    String str2 = null;
    BufferedReader reader = null;
    try {
      reader = new BufferedReader(new InputStreamReader(inputStream));
      while ((str2 = reader.readLine()) != null) {
        str1.append(str2).append("\n");
      }
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      if (reader != null) {
        try {
          reader.close();
        } catch (IOException e1) {
        }
      }
    }
    return str1.toString();
  }

  /**
   * Base64加密
   */
  public static String encodeBase64(String str) throws UnsupportedEncodingException {
    return new String(Base64.encodeBase64(str.getBytes("UTF-8")));
  }

  /**
   * Base64解密
   */
  public static String decodeBase64(String str) throws UnsupportedEncodingException {
    return new String(Base64.decodeBase64(str.getBytes("UTF-8")));
  }

  /**
   * AES密钥
   */
  public static String getAESKey(String str) {
    try {
      KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
      if (isNullStr(str)) {
        keyGenerator.init(128);
      } else {
        keyGenerator.init(128, new SecureRandom(str.getBytes("UTF-8")));
      }
      SecretKey secretKey = keyGenerator.generateKey();
      return new String(Base64.encodeBase64(secretKey.getEncoded()), "UTF-8");
    } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
      e.printStackTrace();
      return null;
    }
  }

  /**
   * AES加密
   */
  public static String encodeAES(String str, String key) {
    try {
      Security.addProvider(new BouncyCastleProvider());
      Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding");
      cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(Base64.decodeBase64(key.getBytes("UTF-8")), "AES"));
      return new String(Base64.encodeBase64(cipher.doFinal(str.getBytes("UTF-8"))), "UTF-8");
    } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | UnsupportedEncodingException e) {
      e.printStackTrace();
      return null;
    }
  }

  /**
   * AES解密
   */
  public static String decodeAES(String str, String key) {
    try {
      Security.addProvider(new BouncyCastleProvider());
      Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding");
      cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(Base64.decodeBase64(key.getBytes("UTF-8")), "AES"));
      return new String(cipher.doFinal(Base64.decodeBase64(str.getBytes("UTF-8"))), "UTF-8");
    } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | UnsupportedEncodingException e) {
      e.printStackTrace();
      return null;
    }
  }

  /**
   * RSA密钥
   */
  public static LinkedHashMap<String, String> getRSAKey(String str) {
    try {
      LinkedHashMap<String, String> rHashMap = new LinkedHashMap<String, String>();
      KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
      if (isNullStr(str)) {
        keyPairGenerator.initialize(4096, new SecureRandom());
      } else {
        keyPairGenerator.initialize(4096, new SecureRandom(str.getBytes("UTF-8")));
      }
      KeyPair keyPair = keyPairGenerator.generateKeyPair();
      RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
      RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
      rHashMap.put("privateKey", new String(Base64.encodeBase64(privateKey.getEncoded()), "UTF-8"));
      rHashMap.put("publicKey", new String(Base64.encodeBase64(publicKey.getEncoded()), "UTF-8"));
      return rHashMap;
    } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
      e.printStackTrace();
      return null;
    }
  }

  /**
   * RSA私钥加密
   */
  public static String encodeRSAByPrivateKey(String str, String key) {
    try {
      Cipher cipher = Cipher.getInstance("RSA");
      cipher.init(Cipher.ENCRYPT_MODE, (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(Base64.decodeBase64(key.getBytes("UTF-8")))));
      return new String(Base64.encodeBase64(cipher.doFinal(str.getBytes("UTF-8"))), "UTF-8");
    } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | InvalidKeySpecException | UnsupportedEncodingException e) {
      e.printStackTrace();
      return null;
    }
  }

  /**
   * RSA公钥解密
   */
  public static String decodeRSAByPublicKey(String str, String key) {
    try {
      Cipher cipher = Cipher.getInstance("RSA");
      cipher.init(Cipher.DECRYPT_MODE, (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(Base64.decodeBase64(key.getBytes("UTF-8")))));
      return new String(cipher.doFinal(Base64.decodeBase64(str.getBytes("UTF-8"))), "UTF-8");
    } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | InvalidKeySpecException | UnsupportedEncodingException e) {
      e.printStackTrace();
      return null;
    }
  }

  /**
   * RSA公钥加密
   */
  public static String encodeRSAByPublicKey(String str, String key) {
    try {
      Cipher cipher = Cipher.getInstance("RSA");
      cipher.init(Cipher.ENCRYPT_MODE, (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(Base64.decodeBase64(key.getBytes("UTF-8")))));
      return new String(Base64.encodeBase64(cipher.doFinal(str.getBytes("UTF-8"))), "UTF-8");
    } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | InvalidKeySpecException | UnsupportedEncodingException e) {
      e.printStackTrace();
      return null;
    }
  }

  /**
   * RSA私钥解密
   */
  public static String decodeRSAByPrivateKey(String str, String key) {
    try {
      Cipher cipher = Cipher.getInstance("RSA");
      cipher.init(Cipher.DECRYPT_MODE, (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(Base64.decodeBase64(key.getBytes("UTF-8")))));
      return new String(cipher.doFinal(Base64.decodeBase64(str.getBytes("UTF-8"))), "UTF-8");
    } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException | InvalidKeySpecException | UnsupportedEncodingException e) {
      e.printStackTrace();
      return null;
    }
  }

  /**
   * 变一棵树
   */
  public static CoreTree<?> toTree(Collection<CoreTree<?>> treeSet, Boolean rootNodeExpand) {
    return CoreTool.toTree(treeSet, null, null, null, null, null, rootNodeExpand, null, null, null);
  }

  /**
   * 变一棵树
   */
  public static CoreTree<?> toTree(Collection<CoreTree<?>> treeSet, String name) {
    return CoreTool.toTree(treeSet, null, name, null, name, name, null, null, null, null);
  }

  /**
   * 变一棵树
   */
  public static CoreTree<?> toTree(Collection<CoreTree<?>> treeSet, Boolean rootNodeExpand, String name) {
    return CoreTool.toTree(treeSet, null, name, null, name, name, rootNodeExpand, null, null, null);
  }

  /**
   * 变一棵树
   */
  public static CoreTree<?> toTree(Collection<CoreTree<?>> treeSet, String rootNodeId, String rootNodeName, String rootNodeTkey, String rootNodeTitle, String rootNodeValue, Boolean rootNodeExpand, Boolean rootNodeSelected, Boolean rootNodeChecked, Boolean rootNodeDisabled) {
    CoreTree<?> tree = new CoreTree<>(rootNodeExpand, rootNodeSelected, rootNodeChecked, rootNodeDisabled)
        .setId(CoreTool.isNotNullStr(rootNodeId) ? rootNodeId : "0")
        .setName(CoreTool.isNotNullStr(rootNodeName) ? rootNodeName : "/")
        .setTkey(CoreTool.isNotNullStr(rootNodeTkey) ? rootNodeTkey : "0")
        .setTitle(CoreTool.isNotNullStr(rootNodeTitle) ? rootNodeTitle : "/")
        .setValue(CoreTool.isNotNullStr(rootNodeValue) ? rootNodeValue : "0");
    if (CoreTool.isNotEmpty(treeSet)) {
      Collection<CoreTree<?>> rTreeSet = new ArrayList<CoreTree<?>>();
      for (CoreTree<?> c : treeSet) {
        if (CoreTool.isNullStr(c.getPid())) {
          rTreeSet.add(c);
          continue;
        }
        for (CoreTree<?> p : treeSet) {
          if (CoreTool.isNotNullStr(p.getId()) && p.getId().equals(c.getPid())) {
            c.setPnode(true);
            p.getChildren().add(c);
            p.setCnode(true);
          }
        }
      }
      if (rTreeSet.size() == 1) {
        tree = rTreeSet.iterator().next();
        tree.setExpand(rootNodeExpand != null && rootNodeExpand ? true : false);
      } else {
        for (CoreTree<?> eo : rTreeSet) {
          eo.setPid("0");
          eo.setPnode(true);
        }
        tree.setChildren(rTreeSet);
        tree.setCnode(true);
      }
    }
    return tree;
  }

  /**
   * 展开树
   */
  public static void toExpandTree(CoreTree<?> tree) {
    CoreTool.toExpandTree(null, tree);
  }

  /**
   * 展开树
   */
  public static void toExpandTree(CoreTree<?> ptree, CoreTree<?> ctree) {
    if (CoreTool.isNotEmpty(ctree.getChildren())) {
      for (CoreTree<?> tree : ctree.getChildren()) {
        CoreTool.toExpandTree(ctree, tree);
      }
      if (CoreTool.isNotNullStr(ctree.getPid())) {
        if (ptree != null) {
          ptree.setExpand(ctree.getChecked() || ctree.getExpand());
        }
      }
    } else {
      if (CoreTool.isNotNullStr(ctree.getPid())) {
        if (ptree != null) {
          ptree.setExpand(ctree.getChecked() || ctree.getExpand());
        }
      }
    }
  }

  /**
   * 变一棵加载树
   */
  public static CoreLoadTree<?> toLoadTree(Collection<CoreLoadTree<?>> treeSet, Boolean rootNodeExpand) {
    return CoreTool.toLoadTree(treeSet, null, null, null, null, null, rootNodeExpand, null, null);
  }

  /**
   * 变一棵加载树
   */
  public static CoreLoadTree<?> toLoadTree(Collection<CoreLoadTree<?>> treeSet, String name) {
    return CoreTool.toLoadTree(treeSet, null, name, null, name, name, null, null, null);
  }

  /**
   * 变一棵加载树
   */
  public static CoreLoadTree<?> toLoadTree(Collection<CoreLoadTree<?>> treeSet, Boolean rootNodeExpand, String name) {
    return CoreTool.toLoadTree(treeSet, null, name, null, name, name, rootNodeExpand, null, null);
  }

  /**
   * 变一棵加载树
   */
  public static CoreLoadTree<?> toLoadTree(Collection<CoreLoadTree<?>> treeSet, String rootNodeId, String rootNodeName, String rootNodeTkey, String rootNodeTitle, String rootNodeValue, Boolean rootNodeExpand, Boolean rootNodeSelected, Boolean rootNodeChecked) {
    CoreLoadTree<?> tree = new CoreLoadTree<>(rootNodeExpand, rootNodeSelected, rootNodeChecked)
        .setId(CoreTool.isNotNullStr(rootNodeId) ? rootNodeId : "0")
        .setName(CoreTool.isNotNullStr(rootNodeName) ? rootNodeName : "/")
        .setTkey(CoreTool.isNotNullStr(rootNodeTkey) ? rootNodeTkey : "0")
        .setTitle(CoreTool.isNotNullStr(rootNodeTitle) ? rootNodeTitle : "/")
        .setValue(CoreTool.isNotNullStr(rootNodeValue) ? rootNodeValue : "0");
    if (CoreTool.isNotEmpty(treeSet)) {
      Collection<CoreLoadTree<?>> rTreeSet = new ArrayList<CoreLoadTree<?>>();
      for (CoreLoadTree<?> c : treeSet) {
        if (CoreTool.isNullStr(c.getPid())) {
          rTreeSet.add(c);
          continue;
        }
        for (CoreLoadTree<?> p : treeSet) {
          if (CoreTool.isNotNullStr(p.getId()) && p.getId().equals(c.getPid())) {
            c.setPnode(true);
            p.getChildren().add(c);
            p.setCnode(true);
          }
        }
      }
      if (rTreeSet.size() == 1) {
        tree = rTreeSet.iterator().next();
        tree.setExpand(rootNodeExpand != null && rootNodeExpand ? true : false);
      } else {
        for (CoreLoadTree<?> eo : rTreeSet) {
          eo.setPid("0");
          eo.setPnode(true);
        }
        tree.setChildren(rTreeSet);
        tree.setCnode(true);
      }
    }
    return tree;
  }

  /**
   * 展开加载树
   */
  public static void toExpandLoadTree(CoreLoadTree<?> tree) {
    CoreTool.toExpandLoadTree(null, tree);
  }

  /**
   * 展开加载树
   */
  public static void toExpandLoadTree(CoreLoadTree<?> ptree, CoreLoadTree<?> ctree) {
    if (CoreTool.isNotEmpty(ctree.getChildren())) {
      for (CoreLoadTree<?> tree : ctree.getChildren()) {
        CoreTool.toExpandLoadTree(ctree, tree);
      }
      if (CoreTool.isNotNullStr(ctree.getPid())) {
        if (ptree != null) {
          ptree.setExpand(ctree.getChecked() || ctree.getExpand());
        }
      }
    } else {
      if (CoreTool.isNotNullStr(ctree.getPid())) {
        if (ptree != null) {
          ptree.setExpand(ctree.getChecked() || ctree.getExpand());
        }
      }
    }
  }

  /**
   * 获取当前时间戳
   */
  public static Long getCurrentTimeStamp() {
    return LocalDateTime.now().toInstant(ZoneOffset.ofHours(8)).toEpochMilli();
  }

  /**
   * 获取当前格式化时间
   */
  public static String getCurrentFormatTime(String pattern) {
    return LocalDateTime.now().format(DateTimeFormatter.ofPattern(CoreTool.isNotNullStr(pattern) ? pattern : "yyyy-MM-dd HH:mm:ss"));
  }

  /**
   * 获取当前格式化时间
   */
  public static String getCurrentFormatTime() {
    return CoreTool.getCurrentFormatTime(null);
  }

  /**
   * 时间戳 >>> 格式化时间
   */
  public static String getFormatTimeByTimeStamp(Long timeStamp, String pattern) {
    return Instant.ofEpochMilli(timeStamp).atZone(ZoneOffset.ofHours(8)).toLocalDateTime().format(DateTimeFormatter.ofPattern(CoreTool.isNotNullStr(pattern) ? pattern : "yyyy-MM-dd HH:mm:ss"));
  }

  /**
   * 时间戳 >>> 格式化时间
   */
  public static String getFormatTimeByTimeStamp(Long timeStamp) {
    return CoreTool.getFormatTimeByTimeStamp(timeStamp, null);
  }

  /**
   * 格式化时间 >>> 时间戳
   */
  public static Long getTimeStampByFormatTime(String formatTime, String pattern) {
    try {
      return LocalDateTime.parse(formatTime, DateTimeFormatter.ofPattern(CoreTool.isNotNullStr(pattern) ? pattern : "yyyy-MM-dd HH:mm:ss")).toInstant(ZoneOffset.ofHours(8)).toEpochMilli();
    } catch (Exception e) {
      return LocalDate.parse(formatTime, DateTimeFormatter.ofPattern(CoreTool.isNotNullStr(pattern) ? pattern : "yyyy-MM-dd")).atStartOfDay(ZoneOffset.ofHours(8)).toInstant().toEpochMilli();
    }
  }

  /**
   * 格式化时间 >>> 时间戳
   */
  public static Long getTimeStampByFormatTime(String formatTime) {
    return CoreTool.getTimeStampByFormatTime(formatTime, null);
  }

  /**
   * 源格式化时间 >>> 目标格式化时间
   */
  public static String getFormatTimeByFormatTime(String sourceFormatTime, String sourcePattern, String targetPattern) {
    try {
      return LocalDateTime.parse(sourceFormatTime, DateTimeFormatter.ofPattern(CoreTool.isNotNullStr(sourcePattern) ? sourcePattern : "yyyy-MM-dd HH:mm:ss")).format(DateTimeFormatter.ofPattern(CoreTool.isNotNullStr(targetPattern) ? targetPattern : "yyyy-MM-dd HH:mm:ss"));
    } catch (Exception e) {
      return LocalDate.parse(sourceFormatTime, DateTimeFormatter.ofPattern(CoreTool.isNotNullStr(sourcePattern) ? sourcePattern : "yyyy-MM-dd")).format(DateTimeFormatter.ofPattern(CoreTool.isNotNullStr(targetPattern) ? targetPattern : "yyyy-MM-dd"));
    }
  }

  /**
   * 源格式化时间 >>> 目标格式化时间
   */
  public static String getFormatTimeByFormatTime(String sourceFormatTime, String sourcePattern) {
    return CoreTool.getFormatTimeByFormatTime(sourceFormatTime, sourcePattern, null);
  }

  /**
   * like查询 >>> 添加前缀和后缀
   */
  public static String likePrefixSuffix(String likeValue) {
    return "%" + likeValue + "%";
  }

  /**
   * like查询 >>> 添加前缀
   */
  public static String likePrefix(String likeValue) {
    return "%" + likeValue;
  }

  /**
   * like查询 >>> 添加后缀
   */
  public static String likeSuffix(String likeValue) {
    return likeValue + "%";
  }

  /**
   * 数组 >>> 字符串
   */
  public static String getStrByList(Collection<String> list) {
    return CoreTool.getStrByList(list, null);
  }

  /**
   * 数组 >>> 字符串
   */
  public static String getStrByList(Collection<String> list, String str) {
    StringBuilder rStr = new StringBuilder();
    if (CoreTool.isNullStr(str)) {
      str = ",";
    }
    if (CoreTool.isNotEmpty(list)) {
      boolean isFirst = true;
      for (String s : list) {
        if (isFirst) {
          isFirst = false;
        } else {
          rStr.append(str);
        }
        rStr.append(s);
      }
    }
    return rStr.toString();
  }

}
